#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>

#define ZX_CHARDEV_MAJOR 200 //主设备号
#define ZX_CHARDEV_NAME "zxchardev" // 设备名称

static char kernelBuf[100] = {"kernel data is coming!"};
static char readBuf[100];
static char writeBuf[100];
static ssize_t zx_chardev_read(struct file *file, char __user *buf, size_t count,
			   loff_t *ppos)
{
    memcpy(readBuf, kernelBuf, count);
	int code = copy_to_user(buf, readBuf, count);
	if(code == 0)
		return count;
	return 0;
}

static ssize_t zx_chardev_write(struct file *file, const char __user *buf, 
size_t count, loff_t *ppos){
	int ret = 0;
	ret = copy_from_user(writeBuf, buf, count);
	memcpy(kernelBuf, writeBuf, count);
	if(ret == 0)
		return count;
	return 0;
}

int zx_chardev_open(struct inode *node, struct file *file){
	printk("zanxin: zx_chardev_open\n");
	memset(readBuf, 0, 100);
	memset(writeBuf, 0, 100);
	char buf[100] = "kernel data is coming!";
	memcpy(kernelBuf, buf, 100);
	return 0;
}

int zx_chardev_release(struct inode *node, struct file *file){
	printk("zanxin: zx_chardev_release\n");
	memset(readBuf, 0, 100);
	memset(writeBuf, 0, 100);
	char buf[100] = "kernel data is coming!";
	memcpy(kernelBuf, buf, 100);
	return 0;
}

static const struct file_operations zx_chardev_fops = {
	.owner		= THIS_MODULE,
	.read		= zx_chardev_read,
	.write		= zx_chardev_write,
	.open		= zx_chardev_open,
	.release	= zx_chardev_release,
};

static int __init chardevbase_init(void){
	register_chrdev(ZX_CHARDEV_MAJOR, ZX_CHARDEV_NAME, &zx_chardev_fops);
    printk(KERN_INFO "zanxin: chardevbase_init\n");
    return 0;
}

static void __exit chardevbase_exit(void)
{
	unregister_chrdev(ZX_CHARDEV_MAJOR, ZX_CHARDEV_NAME);
	printk(KERN_INFO "zanxin: chardevbase_exit\n");
}

// 模块入口与出口
module_init(chardevbase_init);
module_exit(chardevbase_exit);

MODULE_DESCRIPTION("chardev test");
MODULE_AUTHOR("zanxin");
MODULE_LICENSE("GPL v2");